<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    // es5中没有es6中的 extends 关键字，使用组合方式实现继承
    // 使用function.call方法继承属性，因为call方法可以自定义this指向
    // 使用原型继承方法
    
    // 父构造函数
    function Father(name, age) {
        this.name = name 
        this.age = age 
    }
    Father.prototype.sing = function() {
        console.log(this.name, '我会唱歌')
    }

    // 子构造函数 
    function Son(name, age, score) {
        Father.call(this, name, age) // 继承属性 
        this.score = score 
    }
    // Son.protorype = Father.prototype // 不能这样写，否则子类添加的新方法也会被添加到父类中 
    Son.prototype = new Father() // 继承方法 
    Son.prototype.constructor = Son // 改变了原型对象，别忘了把原型对象的constructor改回来 
    Son.prototype.exam = function() {
        console.log(this.name, '要考试')
    }

    // 测试 
    let son = new Son('刘德华', 18, 90) 
    console.log(son) // Son  {name: '刘德华', age: 18, score: 90} 
    son.sing() // 刘德华 我会唱歌 
    son.exam() // 刘德华 要考试 



    // es6中class的本质
    class Animal {

    }
    console.log(typeof Animal) // function 
    // 1.类的本质还是一个函数，我们也可以简单地认为，类就是构造函数的另外一种写法
    // （1）类有原型对象prototype
    console.log(Animal.prototype) // 有 
    // （2）类原型对象中constructor指向构造函数本身
    console.log(Animal.prototype.constructor === Animal) // true 
    // （3）类可以通过prototype添加方法
    Animal.prototype.sing = function(){ console.log('我会唱歌') }
    new Animal().sing() // 我会唱歌 
    // （4）类创建的实例对象有__proto__属性，指向类的protorype属性
    console.log(new Animal().__proto__ === Animal.prototype) // true 
    

</script>
</html>